﻿/*******************************************************************
Copyright (c) 2011 이재범

*  Permission is hereby granted, free of charge, to any person
*  obtaining a copy of this software and associated documentation
*  files (the "Software"), to deal in the Software without
*  restriction, including without limitation the rights to use,
*  copy, modify, merge, publish, distribute, sublicense, and/or sell
*  copies of the Software, and to permit persons to whom the
*  Software is furnished to do so, subject to the following
*  conditions:
* 
*  The above copyright notice and this permission notice shall be
*  included in all copies or substantial portions of the Software.
* 
*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
*  OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
*  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
*  HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
*  WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
*  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
*  OTHER DEALINGS IN THE SOFTWARE.
*******************************************************************/

#include "internet_data.h"
#include "dictionary.h"
#include "Hash_set.h"
#pragma once

class Equation : public InternetData
{

public:
	static Dictionary<string> operator_list; // 연산자 리스트
	static Dictionary<string> dot_symbol_list; // \cdots, \hdots 등등
	static Dictionary<string> equal_symbol_list; // \equal, \ge 등등
	static Dictionary<string> non_operator_list; // 연산자가 아닌 것들
	static Dictionary<string> binary_operator_list; // 이항 연산자 모음
	static Dictionary<string> changeable_operator_list; // 교환 가능한 연산자 모음
	static Dictionary<string> unchangeable_operator_list; // 교환 불가능한 연산자 모음
	static Dictionary<string> operator_as_symbol_list;
	static Dictionary<string> operand_as_keyword; // 중요한 피연산자는 따로 처리해야 한다 (\int, \sum 등등)

	// 자연어 처리 관련. 참고적으로 특수하게 처리되는 \frac 이나 \over, \minus 등은 제외
	static Dictionary<string> operator_change_from; 
	static Dictionary<string> operator_change_to;
	static Hash_set word_list; 

public:
	string equation;
	bool is_normalized; // 성공적으로 정규화가 되었는지.

	// 다음의 함수들은 equation_common.cpp 에 정의되어 있다
	static bool is_equal_related_operator(string& operator_name); // equal_symbol_list 에 들어있는지 확인한다.
	static bool is_dot(string &operator_name); // dot 관련 연산자 인가?
	static bool is_binary_operator(string &operator_name); // 이항 연산자 인가? (equal, + 연산자들 제외)
	static bool is_two_parameter_operator(string &operator_name); // 이항 연산자 인가 (comma 포함) 
	static bool is_changeable(string &operator_name);
	static bool is_unchangeable(string &operator_name);
	static bool is_operator(string& equation, int i, string& operator_name);
	static bool is_keyword_operand(string &operator_name);

public:

	Equation() {}
	Equation(string _eq) : is_normalized(true)
	{ 
		equation = _eq; 
		natural_language_process(); 
		if(!is_normalized)
			return;

		normalize_equation();
	}

	// 정규화 된 수식을 location 에 추가한다.
	void append_equation_data(string location)
	{
		if(!is_normalized)
			data = '\n';
		else
			data = equation + '\n';

		append_data(location);
	}

	// 다음의 함수들은 normalize_equation.cpp 에 정의되어 있다.
	void normalize_equation(); // 수식에 중괄호를 삽입하여 정규화 한다.
	void enclose_numbers(); // 숫자들을 중괄호로 감싼다. 
	void insert_missing_times(); // 생략된 곱셈 기호를 추가한다. 
	void insert_times_btw_consecutive_brakets(); // {}{} 를 {} \times {} 로 변환한다

	// 다음의 함수들은 natural_language_process.cpp 에 정의되어 있다
	void natural_language_process(); 
	void is_syntax_correct(); // 괄호 등이 맞게 짝지어졌는지 체크
	void adjust_operators(); // 동일한 이름의 연산자나 frac, minus 를 처리
	void adjust_subscript(); // 첨자를 처리한다.
	void adjust_dots(); // 점 들을 처리한다. 
	void adjust_braket(); // 괄호들을 처리한다.
	void adjust_latex(); // Latex 특이적 명령어 (\label, \begin 등) 처리

	// 다음의 함수들은 equation_common.cpp 에 정의되어 있다
	bool is_operator(int i, string& operator_name); // non_operator_list 에 들어있는지 확인한다. 
	bool is_operator_only_for_subscript(int i, string& operator_name); // 위와 같지만, 그대신 operator 를 고를 때 _ 와 @ 를 포함하지 않는다.

	void optimize_space(); // 띄어쓰기를 제거
	void optimize_parenth(); // 괄호들을 최적화한다. 
	void get_symbol_name(int i, string& operator_name); // i 에 위치한 \ 로 시작하는 기호의 이름을 가져온다. 
	int find_match_parenth(int i); // i 위치에 해당하는 괄호와 짝을 이루는 괄호를 찾는다.

};